
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <limits>
#include <cmath>

#include <lurpc/net/socket_server.h>
#include <lurpc/core/rpc_core.h>
#include <lurpc/service/server_stub.h>

namespace srv {

struct MyRecord {
    int32_t x = 0;
    int32_t y = 0;
    float_t z = 0.0;

    std::string name;

    std::vector<std::string> cs;

    MyRecord() = default;

    MyRecord(int32_t _x, int32_t _y, float_t _z, std::string _n, std::vector<std::string> _c)
            : x(_x), y(_y), z(_z), name(std::move(_n)), cs(std::move(_c)) {}

    template<typename Arch>
    void serialize(Arch &_arch) {
        _arch(x, y, z, name, cs);
    }
};

struct MyData {
    int id = 0;
    std::unordered_map<int, MyRecord> ds;

    template<typename Arch>
    void serialize(Arch &_arch) {
        _arch(id, ds);
    }
};

}

namespace srv {

MyData
plusDataLess20
(MyData& _d)
{
    MyData _dd = _d;
    for (auto& [k, v] : _dd.ds) {
        if (k < 20) {
            v.x++;
            v.y++;
            v.z++;
            v.cs.emplace_back("quanhuang");
        }
    }
    return _dd;
}

MyData
addRecordToData
(MyRecord& _in1, MyData& _in2)
{
    MyData _out = _in2;
    int _k = _in2.ds.begin()->first;
    for (auto& [k, v] : _in2.ds) if (k > _k) _k = k;
    _out.ds[_k + 1] = _in1;
    return _out;
}

int
integerMultiply
(int& a, int& b)
{
    return a * b;
}

}

namespace srv {

std::string service_132(const std::string& _msg) {
    using type_tr = lurpc::service_type_traits<MyData, MyData>;
    auto _param_tp = type_tr::deserialize(_msg);
    auto _ret = plusDataLess20(std::get<0>(_param_tp));
    return type_tr::serialize(_ret);
}

std::string service_133(const std::string& _msg) {
    using type_tr = lurpc::service_type_traits<MyData, MyRecord, MyData>;
    auto _param_tp = type_tr::deserialize(_msg);
    auto _ret = addRecordToData(std::get<0>(_param_tp), std::get<1>(_param_tp));
    return type_tr::serialize(_ret);
}

std::string service_134(const std::string& _msg) {
    using type_tr = lurpc::service_type_traits<int, int, int>;
    auto _param_tp = type_tr::deserialize(_msg);
    auto _ret = integerMultiply(std::get<0>(_param_tp), std::get<1>(_param_tp));
    return type_tr::serialize(_ret);
}

}


inline void register_processes() {
    lurpc::server_stub::register_service(132, srv::service_132);
    lurpc::server_stub::register_service(133, srv::service_133);
    lurpc::server_stub::register_service(134, srv::service_134);
}

void start() {
    register_processes();
    lurpc::start_rpc_server(4399, "192.168.71.128");
}

int main(int argc, char** argv) {

    start();

    return 0;
}
